package com.daffodil.flowable.demo.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.daffodil.core.dao.JpaDao;
import com.daffodil.core.entity.Query;
import com.daffodil.core.exception.BaseException;
import com.daffodil.flowable.demo.entity.Expense;
import com.daffodil.flowable.demo.service.IExpenseService;
import com.daffodil.flowable.entity.ActCnModelUser;
import com.daffodil.flowable.util.FlowableUtils;
import com.daffodil.framework.shiro.util.ShiroUtils;
import com.daffodil.system.entity.SysUser;
import com.daffodil.util.DateUtils;
import com.daffodil.util.StringUtils;
import com.daffodil.util.text.StrFormatter;

@Service
public class ExpenseServiceImpl implements IExpenseService{
	/**
	 * 流程开发程序员要先确定模块的所属流程分类
	 */
	private final static String EXPENSE_MODULE_TYPEID = "40283e81703c818201703c83bbe30005"; 

	@Autowired
	private JpaDao jpaDao;
	
	@Autowired
	private RuntimeService runtimeService;
	
	@Override
	public List<Expense> selectExpenseList(Query<Expense> query) {
		String hql = "from Expense where 1=1 ";
		SysUser user = ShiroUtils.getSysUser();
		List<Object> paras = new ArrayList<Object>();
		Expense expense = query.getEntity();
		if(StringUtils.isNotEmpty(expense.getTitle())){
			hql += "and title like ? ";
			paras.add("%" + expense.getTitle() + "%");
		}
		if(!ShiroUtils.isAdmin()){
			hql += "and createBy = ? ";
			paras.add(user.getLoginName());
		}
		if(StringUtils.isNotEmpty(query.getOrderBy())){
			hql += "order by " + query.getOrderBy();
		}
		if(null != query.getPage()){
			return jpaDao.search(hql, paras, Expense.class, query.getPage());
		}else{
			return jpaDao.search(hql, paras, Expense.class);
		}
	}

	@Override
	public Expense selectExpenseById(String expenseId) {
		return jpaDao.find(Expense.class, expenseId);
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional
	public void insertExpense(Expense expense) {
		expense.setCreateBy(ShiroUtils.getLoginName());
		expense.setCreateTime(new Date());
		jpaDao.save(expense);
		
		String hql = "from ActCnModelUser where userId = ? and typeId = ?";
		List<Object> paras = new ArrayList<Object>();
		paras.add(ShiroUtils.getUserId());
		paras.add(EXPENSE_MODULE_TYPEID);
		ActCnModelUser model = jpaDao.find(hql, paras, ActCnModelUser.class);
		if(null == model){
			throw new BaseException("您尚未绑定报销功能的流程，请联系管理员");
		}
		
		//流程实例初始化
		FlowableUtils.startProcessInstanceByKey(expense.getTitle(), 
				model.getTypeId(),
				model.getModelKey(),
				expense.getId(), 
				(Map<String, Object>) JSONObject.toJSON(expense));
	}

	@Override
	@Transactional
	public void updateExpense(Expense expense) {
		expense.setUpdateBy(ShiroUtils.getLoginName());
		expense.setUpdateTime(new Date());
		jpaDao.update(expense);
	}

	@Override
	@Transactional
	public void deleteExpenseByIds(String[] ids) {
		if(StringUtils.isNotEmpty(ids)){
			for(String id : ids){
				ProcessInstance instance = runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(id).singleResult();
				if(null != instance){
					//如果存在正在运行的流程实例，也应删除，并且最好加入删除原因
					String deleteTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date());
					String deleteReason = StrFormatter.format("任务删除成功，操作人：{}，操作时间：{}", ShiroUtils.getLoginName(), deleteTime);
					runtimeService.deleteProcessInstance(instance.getId(), deleteReason);
				}
			}
			jpaDao.delete(Expense.class, ids);
		}
	}

}
